﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using Yunzuan.Foundation.Log;
using Yunzuan.Foundation.Web;

namespace Yunzuan.Foundation.Web_api
{
    public static class MyHttpRequest
    {
        /// <summary>
        /// Post
        /// </summary>
        /// <param name="rif">提交的最终JSON</param>
        /// <param name="signStr">签名后的字符串</param>
        /// <returns></returns>
        public static string PostJSONByRequestParam(RequestInfo rif, int timeout = 3, string guid = "", string signStr = "", int totalSeconds = 0, HttpFileCollection httpFileCollection = null, RequestLib reqLib = 0)
        {
            try
            {
                if (timeout > 0)
                {
                    timeout--;

                    //取数据
                    var httpClient = new HttpClient();
                    httpClient.DefaultRequestHeaders.Connection.Add("keep-alive");//保持长连接
                    //需要签名
                    if (guid != "" && signStr != "" && totalSeconds != 0)
                    {

                        if (httpFileCollection != null)  //上传文件
                        {
                            using (var content = new MultipartFormDataContent())
                            {

                                for (var i = 0; i < httpFileCollection.AllKeys.Count(); i++)
                                {
                                    //content.Add(CreateFileContent(httpFileCollection[i].InputStream, httpFileCollection[i].FileName));
                                    var fileContent = new StreamContent(httpFileCollection[i].InputStream);
                                    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { FileName = ToHexString(httpFileCollection[i].FileName), Name = "file_data" };

                                    content.Add(fileContent);
                                }
                                content.Headers.Add("UUID", guid);
                                content.Headers.Add("Auth", signStr);
                                content.Headers.Add("Time", totalSeconds.ToString());

                                //先屏蔽，因为用的正式数据库 ********************正式上线开通
                                var responseJson = httpClient.PostAsync(rif.RequestUrl, content)
                                 .Result.Content.ReadAsStringAsync().Result;
                                return @responseJson;

                            }
                        }
                        else
                        {
                            if (reqLib == RequestLib.DeleteOrder || reqLib == RequestLib.DeleteSelfStock || reqLib == RequestLib.DELETE)             //DELETE
                            {
                                httpClient.DefaultRequestHeaders.Add("Auth", signStr);
                                httpClient.DefaultRequestHeaders.Add("UUID", guid);
                                httpClient.DefaultRequestHeaders.Add("Time", totalSeconds.ToString());
                                var responseJson = httpClient.DeleteAsync(rif.RequestUrl)
                                     .Result.Content.ReadAsStringAsync().Result;
                                return responseJson;
                            }
                            else if (reqLib == RequestLib.GetSoldOrder || reqLib == RequestLib.GET) //获取订单 GET提交  GetAsync                    //GET
                            {
                                httpClient.DefaultRequestHeaders.Add("Auth", signStr);
                                httpClient.DefaultRequestHeaders.Add("UUID", guid);
                                httpClient.DefaultRequestHeaders.Add("Time", totalSeconds.ToString());
                                var responseJson = httpClient.GetAsync(rif.RequestUrl)
                                     .Result.Content.ReadAsStringAsync().Result;
                                return responseJson;
                            }
                            else
                            {
                                HttpContent httpContent = new StringContent(rif.RequestJson);
                                httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                                httpContent.Headers.Add("UUID", guid);
                                httpContent.Headers.Add("Auth", signStr);
                                httpContent.Headers.Add("Time", totalSeconds.ToString());
                                if (reqLib == RequestLib.UpdateSelfStock || reqLib == RequestLib.UpdateSelfStockDisByBatch || reqLib == RequestLib.PUT)     //PUT
                                {
                                    var responseJson = httpClient.PutAsync(rif.RequestUrl, httpContent)
                                         .Result.Content.ReadAsStringAsync().Result;
                                    return responseJson;
                                }
                                else if (reqLib == RequestLib.AddSelfStock || reqLib == RequestLib.NormalRequest || reqLib == RequestLib.SubmitOrders || reqLib == RequestLib.POST)      //POST
                                {
                                    var responseJson = httpClient.PostAsync(rif.RequestUrl, httpContent)
                                         .Result.Content.ReadAsStringAsync().Result;
                                    return responseJson;
                                }
                            }
                        }
                    }
                    else
                    {
                        HttpContent httpContent = new StringContent(rif.RequestJson);
                        httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                        var responseJson = httpClient.PostAsync(rif.RequestUrl, httpContent)
                            .Result.Content.ReadAsStringAsync().Result;
                        return responseJson;

                    }

                }
                return "";
            }
            catch (Exception ee)
            {
                //this.GetType()  在静态中使用this无效
                Logger.Error(typeof(MyHttpRequest), "method:PostJSONByRequestParam," + ee.Message);
                return PostJSONByRequestParam(rif, timeout, guid, signStr, totalSeconds, httpFileCollection, reqLib);
                throw;
            }

        }

        /// 为字符串中的非英文字符编码  
        /// </summary>  
        /// <param name="s"></param>  
        /// <returns></returns>  
        public static string ToHexString(string s)
        {
            char[] chars = s.ToCharArray();
            StringBuilder builder = new StringBuilder();
            for (int index = 0; index < chars.Length; index++)
            {
                bool needToEncode = NeedToEncode(chars[index]);
                if (needToEncode)
                {
                    string encodedString = ToHexString(chars[index]);
                    builder.Append(encodedString);
                }
                else
                {
                    builder.Append(chars[index]);
                }
            }

            return builder.ToString();
        }

        /// <summary>  
        ///指定 一个字符是否应该被编码  
        /// </summary>  
        /// <param name="chr"></param>  
        /// <returns></returns>  
        private static bool NeedToEncode(char chr)
        {
            string reservedChars = "$-_.+!*'(),@=&";

            if (chr > 127)
                return true;
            if (char.IsLetterOrDigit(chr) || reservedChars.IndexOf(chr) >= 0)
                return false;

            return true;
        }

        /// <summary>  
        /// 为非英文字符串编码  
        /// </summary>  
        /// <param name="chr"></param>  
        /// <returns></returns>  
        private static string ToHexString(char chr)
        {
            UTF8Encoding utf8 = new UTF8Encoding();
            byte[] encodedBytes = utf8.GetBytes(chr.ToString());
            StringBuilder builder = new StringBuilder();
            for (int index = 0; index < encodedBytes.Length; index++)
            {
                builder.AppendFormat("%{0}", Convert.ToString(encodedBytes[index], 16));
            }
            return builder.ToString();
        }

        public static Stream GetFileSteam(string fileName)
        {
            using (FileStream stream = new FileStream(fileName, FileMode.Open))
            {
                byte[] inBytes = new byte[stream.Length];
                stream.Read(inBytes, 0, inBytes.Length);
                byte[] data = inBytes;
                return stream;
            }
        }

        public static StreamContent CreateFileContent(Stream stream, string fileName, string contentType = "")
        {
            var fileContent = new StreamContent(stream);
            fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { FileName = fileName, Name = "file_data" };
            //fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
            return fileContent;
        }


        /// <summary>
        ///转化成搜索库存的格式
        /// </summary>
        /// <param name="responseJson"></param>
        /// <returns></returns>
        public static string ConvertToInventoryFormat(string responseJson)
        {
            //匹配成类的结构 
            //responseJson = responseJson.Replace("Rapnet", "_Rapnet")
            //responseJson = responseJson.Replace("Rapnet", "Rapnet")
            responseJson = responseJson.Replace("rows", "Data")
                .Replace("records", "TotalCount")
                .Replace("result", "Result")
                .Replace("OriginUSDPerGrain", "SourceDolarPerGrain")
                .Replace("OriginDiscountReturn", "SourceDiscountReturn")
                .Replace("InsertTime", "CreateTime")
                .Replace("OriginUSDPerCarat", "SourceDolarPerCarat");
                //.Replace("\"ID\":", "\"InventoryID\":");
            return responseJson;
        }

        /// <summary>
        /// 给字典排序(string,string)
        /// </summary>
        /// <param name="paramSecond"></param>
        /// <returns></returns>
        public static StringBuilder ShotDic(Dictionary<string, string> param)
        {
            IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(param, StringComparer.Ordinal);
            IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();

            //3
            StringBuilder sbStr = new StringBuilder();
            while (dem.MoveNext())
            {
                string key = dem.Current.Key;
                string value = dem.Current.Value;
                //if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
                if (!string.IsNullOrEmpty(key)) //值可能为空
                {
                    sbStr.Append(key).Append(value);
                }
            }
            return sbStr;
        }

        /// <summary>  
        ///   
        /// 将对象属性转换为key-value对  
        /// </summary>  
        /// <param name="o"></param>  
        /// <returns></returns>  
        public static Dictionary<String, String> ObjectToDict(Object o)
        {
            Dictionary<String, String> map = new Dictionary<String, String>();

            Type t = o.GetType();

            PropertyInfo[] pi = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo p in pi)
            {
                MethodInfo mi = p.GetGetMethod();

                if (mi != null && mi.IsPublic)
                {
                    map.Add(p.Name, mi.Invoke(o, new Object[] { }) == null ? null : mi.Invoke(o, new Object[] { }).ToString());
                }
            }

            return map;
        }


        /// <summary>
        /// 给字典排序(string,object)
        /// </summary>
        /// <param name="paramSecond"></param>
        /// <returns></returns>
        public static StringBuilder ShotDic1(Dictionary<string, object> param)
        {
            IDictionary<string, object> sortedParams = new SortedDictionary<string, object>(param, StringComparer.Ordinal);
            IEnumerator<KeyValuePair<string, object>> dem = sortedParams.GetEnumerator();

            //3
            StringBuilder sbStr = new StringBuilder();
            while (dem.MoveNext())
            {
                string key = dem.Current.Key;
                object value = dem.Current.Value;
                //if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))

                if (null == value || value.GetType().Name == "Boolean") //值为bool类型则忽略
                {
                    sbStr.Append(key);
                }
                else if (!string.IsNullOrEmpty(key)) //值可以为空
                {
                    sbStr.Append(key).Append(value);
                }
            }
            return sbStr;
        }

        public static void SignByParams(string guid, string sbStr, out int totalSeconds, out string signStr)
        {
           byte[] secretBytes = Encoding.UTF8.GetBytes(GlobalConfig.AccessSecret);//转utf8的byte,不直接参与签名,用来初始化HMACMD5算法

            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1); //得到日期最小值到现在的总时间秒
            totalSeconds = (int)ts.TotalSeconds;
            //拼接成参数准备加密
            byte[] SignBytes = Encoding.UTF8.GetBytes(totalSeconds.ToString() + guid + sbStr.ToString());


            //6,按约定密钥初始化HMACMD5 
            HMACMD5 myhmacMD5 = new HMACMD5(secretBytes);
            //使用HMAC给拼装好的字符串签名
            byte[] b_Stream = myhmacMD5.ComputeHash(SignBytes);


            //7.将摘要得到的字节流结果使用十六进制小写
            string result = string.Empty;
            for (int i = 0; i < b_Stream.Length; i++)
            {
                result += b_Stream[i].ToString("x2");
            }

            //8.把十六进制摘要使用BASE64编码，
            string s_ResultByBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(result));

            //9拼装到head
            signStr = GlobalConfig.AccessKey + ":" + s_ResultByBase64;
        }
        [Obsolete]  //过时的函数标识 
        //将前端JSON字典格式化参数顺序按AabBcdCD的格式 --递归  old 应该为NestedDictSort2Str
        public static string DictSortAnd2Str(JObject param)
        {
            Dictionary<string, object> lastFrist = new Dictionary<string, object>();
            Dictionary<string, object> paramSecond = new Dictionary<string, object>();
            StringBuilder sbStr = new StringBuilder();
            StringBuilder sbStr2 = new StringBuilder();
            foreach (var item in param)
            {
                if (item.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JObject")
                {
                    sbStr2 = new StringBuilder();
                    paramSecond = new Dictionary<string, object>();
                    //排序
                    JToken record = param[item.Key];
                    foreach (JProperty jp in record)
                    {
                        StringBuilder tmpStr = new StringBuilder();
                        if (jp.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JObject")
                        {
                            tmpStr.Append(DictSortAnd2Str(jp.Value.ToObject<JObject>()));
                        }
                        else if (jp.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JArray")
                        {
                            tmpStr.Append(ArrayToStr((Newtonsoft.Json.Linq.JArray)jp.Value));
                        }
                        else if (jp.Value.Type.ToString() == "Boolean")
                        {
                            continue;
                        }
                        else
                        {
                            tmpStr.Append(jp.Value);
                        }
                        paramSecond.Add(jp.Name, tmpStr.ToString());
                    }
                    sbStr2.Append(MyHttpRequest.ShotDic1(paramSecond));//排二维字典
                    lastFrist.Add(item.Key, sbStr2);  //加入最终的字典
                }
                else if (item.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JArray")
                {
                    lastFrist.Add(item.Key, ArrayToStr((Newtonsoft.Json.Linq.JArray)item.Value));
                }
                else if (item.Value.Type.ToString() == "Boolean")
                {
                    lastFrist.Add(item.Key, null);
                }//发现Float等类型如果不抽离出来，系统会将如0.0xx转为0,导致401
                else if (item.Value.Type.ToString() == "Float" || item.Value.Type.ToString() == "Double")
                {
                    lastFrist.Add(item.Key, item.Value.Parent.ToString().Replace("\"" + item.Key + "\": ", ""));
                }
                else
                {
                    lastFrist.Add(item.Key, item.Value);
                }
            }
            sbStr.Append(MyHttpRequest.ShotDic1(lastFrist));  //排一维字典
            return sbStr.ToString();
        }


        // 11-29

        //将前端JSON字典格式化参数顺序按AabBcdCD的格式 --递归
        //public static string DictSortAnd2Str(JObject param)
        //{
        //    Dictionary<string, object> lastFrist = new Dictionary<string, object>();
        //    Dictionary<string, object> paramSecond = new Dictionary<string, object>();
        //    StringBuilder sbStr = new StringBuilder();
        //    StringBuilder sbStr2 = new StringBuilder();
        //    foreach (var item in param)
        //    {
        //        if (item.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JObject")
        //        {
        //            sbStr2 = new StringBuilder();
        //            paramSecond = new Dictionary<string, object>();
        //            //排序
        //            JToken record = param[item.Key];
        //            foreach (JProperty jp in record)
        //            { 
        //                StringBuilder tmpStr = new StringBuilder();
        //                if (jp.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JObject")
        //                {
        //                    tmpStr.Append(DictSortAnd2Str(jp.Value.ToObject<JObject>()));
        //                }
        //                else if (jp.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JArray")
        //                {
        //                    tmpStr.Append(ArrayToStr((Newtonsoft.Json.Linq.JArray)jp.Value));
        //                }
        //                else if (jp.Value.Type.ToString() == "Boolean")
        //                {
        //                }
        //                else
        //                {
        //                    tmpStr.Append(jp.Value);
        //                }
        //                paramSecond.Add(jp.Name, tmpStr.ToString());
        //            }
        //            sbStr2.Append(MyHttpRequest.ShotDic1(paramSecond));//排二维字典
        //            lastFrist.Add(item.Key, sbStr2);  //加入最终的字典
        //        }
        //        else if (item.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JArray")
        //        {
        //            lastFrist.Add(item.Key, ArrayToStr((Newtonsoft.Json.Linq.JArray)item.Value));
        //        }
        //        else if (item.Value.Type.ToString() == "Boolean")
        //        {
        //            lastFrist.Add(item.Key, null);
        //        }
        //        else
        //        {
        //            lastFrist.Add(item.Key, item.Value);
        //        }
        //    }
        //    sbStr.Append(MyHttpRequest.ShotDic1(lastFrist));  //排一维字典
        //    return sbStr.ToString();
        //}



        private static string ArrayToStr(JArray jp)
        {
            StringBuilder tmpStr = new StringBuilder();
            List<JToken> ps = jp.ToList(); //是数组

            for (int i = 0; i < ps.Count(); i++)
            {
                tmpStr.Append(ps[i]);
            }
            return tmpStr.ToString();
        }

        /// <summary>
        /// 所有请求类型
        /// </summary>
        public enum RequestLib
        {
            /// <summary>
            /// 普通请求
            /// </summary>
            NormalRequest,
            /// <summary>
            /// 更新自己的库存 //对应API 编辑库存，PUT
            /// </summary>
            UpdateSelfStock,
            /// <summary>
            /// 批量修改退点 //对应API 库存改价，PUT
            /// </summary>
            UpdateSelfStockDisByBatch,
            /// <summary>
            /// 添加新的库存 //POST（新增库存）
            /// </summary>
            AddSelfStock,
            /// <summary>
            /// 批量添加新的库存(上传自己的货)//POST 库存导入（需要HTTPS   
            /// </summary>
            ImportSelfStock,
            /// <summary>
            /// 删除订单 DELETE（删除订单）orders/333,444
            /// </summary>
            DeleteOrder,

            /// <summary>
            /// 订单提交POST（提交订单） orders/?id=333,444
            /// </summary>
            SubmitOrders,

            /// <summary>
            /// 订单读取GET（获取订单) orders/?id=333,444
            /// </summary>
            GetSoldOrder,

            /// <summary>
            /// 删除自己的库存stocks/?id=333,444  DELETE
            /// </summary>
            DeleteSelfStock,
            POST,// 11-23
            PUT,
            GET,
            DELETE

        };



        ////////////////////////////// 嵌套解析 11-22////////////////////////////////

        //将前端JSON字典格式化参数顺序按AabBcdCD的格式 --递归
        public static string NestedDictSort2Str(JObject param)
        {
            param = (JObject)ObjShort2Obj(param); //排序
            var str = new StringBuilder();
            foreach (var item in param)
            {
                if (item.Value.Type.ToString() == "Object")
                    str.Append(item.Key + NestedDictSort2Str((JObject)item.Value));
                else if (item.Value.Type.ToString() == "Array")
                    str.Append(item.Key + Array2Str((JArray)item.Value));
                else if (item.Value.Type.ToString() == "Boolean" || string.IsNullOrEmpty(item.Value.ToString()))
                    str.Append(item.Key);
                else str.Append(item.Key + item.Value);
            }
            return str.ToString();
        }

        //数组取值
        public static string Array2Str(JArray array)
        {
            var str = new StringBuilder();
            List<JToken> ps = array.ToList(); //是数组
            for (int i = 0; i < ps.Count(); i++)
            {
                if (ps[i].Type.ToString() == "Object")
                    str.Append(NestedDictSort2Str((JObject)ps[i]));
                else if (ps[i].Type.ToString() == "Array")
                    str.Append(Array2Str((JArray)ps[i]));
                else if (ps[i].Type.ToString() != "Boolean" && !string.IsNullOrEmpty(ps[i].ToString()))
                    str.Append(ps[i]);
            }
            return str.ToString();
        }

        public static JObject ObjShort2Obj(JObject obj)
        {
            var a = new { ID = "", SN = "" };
            var json = JsonConvert.SerializeObject(a);
            JsonConvert.DeserializeAnonymousType(json, a);

            Dictionary<string, object> d = new Dictionary<string, object>();
            foreach (var item in obj)
                d.Add(item.Key, item.Value);  //填充到字典中

            d = d.OrderBy(t => t.Key, StringComparer.Ordinal).ToDictionary(o => o.Key, p => p.Value);  //排序区分大小写
            return JsonConvert.DeserializeObject<JObject>(JsonConvert.SerializeObject(d)); //封装成JObject
        }




        // 11-23


        //将前端JSON字典格式化参数顺序按AabBcdCD的格式 --递归
        //public static string DictSortAnd2Str(JObject param)
        //{
        //    Dictionary<string, object> lastFrist = new Dictionary<string, object>();
        //    Dictionary<string, object> paramSecond = new Dictionary<string, object>();
        //    StringBuilder sbStr = new StringBuilder();
        //    StringBuilder sbStr2 = new StringBuilder();
        //    foreach (var item in param)
        //    {
        //        if (item.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JObject")
        //        {
        //            sbStr2 = new StringBuilder();
        //            paramSecond = new Dictionary<string, object>();
        //            //排序
        //            JToken record = param[item.Key];
        //            foreach (JProperty jp in record)
        //            {
        //                StringBuilder tmpStr = new StringBuilder();
        //                if (jp.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JObject")
        //                {
        //                    tmpStr.Append(DictSortAnd2Str(jp.Value.ToObject<JObject>()));
        //                }
        //                else if (jp.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JArray")
        //                {
        //                    tmpStr.Append(ArrayToStr((Newtonsoft.Json.Linq.JArray)jp.Value));
        //                }
        //                else if (jp.Value.Type.ToString() == "Boolean")
        //                {
        //                    continue;
        //                }
        //                else
        //                {
        //                    tmpStr.Append(jp.Value);
        //                }
        //                paramSecond.Add(jp.Name, tmpStr.ToString());
        //            }
        //            sbStr2.Append(MyHttpRequest.ShotDic1(paramSecond));//排二维字典
        //            lastFrist.Add(item.Key, sbStr2);  //加入最终的字典
        //        }
        //        else if (item.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JArray")
        //        {
        //            lastFrist.Add(item.Key, ArrayToStr((Newtonsoft.Json.Linq.JArray)item.Value));
        //        }
        //        else if (item.Value.Type.ToString() == "Boolean")
        //        {
        //            lastFrist.Add(item.Key, null);
        //        }//发现Float等类型如果不抽离出来，系统会将如0.0xx转为0,导致401
        //        else if (item.Value.Type.ToString() == "Float" || item.Value.Type.ToString() == "Double")
        //        {
        //            lastFrist.Add(item.Key, item.Value.Parent.ToString().Replace("\"" + item.Key + "\": ", ""));
        //        }
        //        else
        //        {
        //            lastFrist.Add(item.Key, item.Value);
        //        }
        //    }
        //    sbStr.Append(MyHttpRequest.ShotDic1(lastFrist));  //排一维字典
        //    return sbStr.ToString();
        //}

        /// <summary>  
        /// 获取一个url中字符串中？后面的值，以Dictionary<key, value>形式返回  
        /// </summary>  
        /// <param name="url">url</param>  
        /// <returns>Dictionary<key, value>形式返回</returns>  
        public static Dictionary<string, string> GetParams(string url)
        {
            int intPos = url.IndexOf("?");
            if (url == null || url.Length < 0 || intPos < 0) //0可以为参数部分解析如上传: ?is_append=1
            {
                return null;
            }
            else
            {
                Dictionary<string, string> dt = new Dictionary<string, string>();
                string strRight = url.Substring(intPos + 1);
                string[] arrPram = StringSplit(strRight, '&');
                for (int i = 0; i < arrPram.Length; i++)
                {
                    string[] arrPramName = StringSplit(arrPram[i], '=');
                    dt.Add(arrPramName[0].ToLower(), arrPramName[1].ToLower());
                }
                return dt;
            }
        }
        public static string[] StringSplit(string str, char chatStr)
        {
            return str.Split(chatStr);
        }
        //获取当前父辈方法及参数名
        public static string GetMethodInfo(Exception ex,out string param)
        {
            string str = "方法名：{0}，参数名：{1}，行号：{3} ,参数值：";
            StackTrace st = new StackTrace(true);
            MethodBase mb = st.GetFrame(1).GetMethod();
            //取得父方法名
            var line = ex.StackTrace.Substring(ex.StackTrace.IndexOf("行号"), ex.StackTrace.Length - ex.StackTrace.IndexOf("行号")); //行号
            //取得父参数名
            if (mb.GetParameters().Count() > 0){
               
                    param=mb.GetParameters()[0].Name;
                    str = string.Format(str, mb.DeclaringType.FullName, line);
            }
            else{
                param="";
                str = string.Format(str, mb.DeclaringType.FullName, "无", line); 
            }
            return str;
        }
    }
}
